package com.learn.excel.core.handler;

import com.alibaba.fastjson.JSON;
import com.learn.excel.core.common.LoginUser;
import com.learn.excel.core.consts.RedisConst;

import com.hawkeye.redis.util.RedisUtil;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author anri
 * @date 2020/10/10 8:27
 */
//@Component
public class RedisHandle {

    @Resource
    private RedisUtil redisUtil;

    public int keyStatus(String keyPattern) {
        List<Integer> res = new ArrayList<>();
        Set keys = redisUtil.keys(keyPattern);
        for (Object key : keys) {
            String s = get(key.toString());
            if (null != s) {
                res.add(Integer.parseInt(s));
            }
        }
        Optional<Integer> max = res.stream().max(Comparator.comparingInt(o -> o));
        return max.orElse(0);
    }

    public void set(String key, Object value) {
        redisUtil.set(key, value);
    }

    public String get(String key) {
        Object res = redisUtil.get(key);
        return res != null ? String.valueOf(res) : null;
    }

    /**
     * 删除当前用户的 token 信息
     *
     * @param token
     * @return
     */
    public void delUserToken(String token) {
        String key = RedisConst.EntityCacheKey.SYSTEM + ":token:";
        redisUtil.del(key + token);
    }

    /**
     * 查询数据初始化任务标识,如果为1，则缓存已发生修改，如果为0，则为发生变化。
     * key -> hk:task:init
     */
    public int getInitTask() {
        Object object = redisUtil.get(RedisConst.EntityCacheKey.DATA_INIT_TASK);
        if (object != null && "1".equals(object.toString())) {
            return RedisConst.DATA_INIT_YES;
        } else {
            return RedisConst.DATA_INIT_NO;
        }
    }

    /**
     * 设置数据初始化任务标识，值为当前时间戳
     * 当缓存发生增删改操作后，此标识设置为1
     * key -> hk:task:init
     */
    public void setInitTask() {
        redisUtil.set(RedisConst.EntityCacheKey.DATA_INIT_TASK, System.currentTimeMillis());
    }

    /**
     * 删除项目列表信息
     * key -> hk:bi:pros
     */
    public void deleteProjects() {
        redisUtil.del(RedisConst.EntityCacheKey.BASEINFO + ":pros");
    }



    /**
     * 添加项目信息到list
     * key -> hk:bi:pros
     */
    public List<Object> getAllProjects() {
        List<Object> objects = redisUtil.lGet(RedisConst.EntityCacheKey.BASEINFO + ":pros", 0, -1);
        return objects;
    }



    /**
     * 删除传感器类型列表信息
     */
    public void deleteTargetTypes() {
        redisUtil.del(RedisConst.EntityCacheKey.BASEINFO + ":tts");
    }





    /**
     * 删除传感器指标列表信息
     */
    public void deleteAllQuotas(int typeId) {
        redisUtil.del(RedisConst.EntityCacheKey.BASEINFO + ":qts:tt:" + typeId);
    }

    /**
     * 设置指标信息
     * key -> hk:bi:qt:{targetTypeId_quotaCode}
     *
     * @param dataQuota


    /**
     * 根据传感器类型设置指标信息
     * key -> hk:bi:qts:tt
     *
     * @param dataQuota
     */
//    public void hsetQuotaByType(SettingsDataQuota dataQuota) {
//        redisUtil.hset(RedisConst.EntityCacheKey.BASEINFO + ":qts:tt:" + dataQuota.getTargetTypeId(),String.valueOf(dataQuota.getCode()), dataQuota);
//    }

    /**
     * 根据传感器类型和指标编号查询指标信息
     * key -> hk:bi:qts:tt
     *
     * @param typeId
     * @param quotaCode
     */
//    public SettingsDataQuota hgetQuotaByTypeAndCode(int typeId, int quotaCode) {
//        Object object = redisUtil.hget(RedisConst.EntityCacheKey.BASEINFO + ":qts:tt:" + typeId, String.valueOf(quotaCode));
//        if(null != object){
//            return (SettingsDataQuota)object;
//        }
//        return null;
//    }



    /**
     * 查询下所有传感器信息
     * key -> hk:bi:tg:{targetId}
     *
     * @param projectId
     */
    public List<Object> getTargetsByProject(Integer projectId) {
        List<Object> objects = redisUtil.lGet(RedisConst.EntityCacheKey.BASEINFO + ":pro:tgs:" + projectId, 0, -1);
        return objects;
    }


    public List<Object> lAll(String key) {
        return redisUtil.lGet(key, 0, -1);
    }

    public List<String> lGetAll(String key) {
        List<Object> objects = redisUtil.lGet(key, 0, -1);
        List<String> resList = new ArrayList<>();
        if (objects != null) {
            for (Object object : objects) {
                resList.add(object.toString());
            }
        }
        return resList;
    }

    public void lSet(String key, Object value) {
        redisUtil.lSet(key, value);
    }

    public void lSetAll(String key, List<Object> values) {
        for (Object value : values) {
            redisUtil.lSet(key, value);
        }
    }


    /**
     * 用于AES验证token存储。
     * key1: hk:sys:token:{userid}
     * key2: hk:sys.token:{token}
     *
     * @param token
     * @param seconds 过期时间（秒）
     */
    public void setAESToken(String token, long seconds) {
        String key = RedisConst.EntityCacheKey.SYSTEM + ":aes:token:";
        redisUtil.set(key + token, token);
        redisUtil.expire(key + token, seconds);
    }

    /**
     * 删除 key
     */
    public void delKey(String key) {
        redisUtil.del(key);
    }

    /**
     * 根据 pattern 删除 key
     */
    public void delKeyPattern(String keyPattern) {
        Set keys = redisUtil.keys(keyPattern + "*");
        for (Object key : keys) {
            redisUtil.del(key.toString());
        }
    }

    /**
     * 查询AES验证token。
     *
     * @param token
     * @return
     */
    public String getAESToken(String token) {
        String key = RedisConst.EntityCacheKey.SYSTEM + ":aes:token:";
        Object object = redisUtil.get(key + token);
        if (object != null) {
            return object.toString();
        }
        return null;
    }

    /**
     * 设置token到redis，并设置超时时间为30分钟。
     * key1: hk:sys:token:{userid}
     * key2: hk:sys.token:{token}
     *
     * @param loginUser
     * @param token
     * @param seconds   过期时间（秒）
     */
    public void setUserToken(LoginUser loginUser, String token, long seconds) {
        String key = RedisConst.EntityCacheKey.SYSTEM + ":token:";
        Integer userId = loginUser.getId();
        redisUtil.set(key + "user:" + userId, token);
        redisUtil.expire(key + "user:" + userId, seconds);
        redisUtil.set(key + token, loginUser);
        redisUtil.expire(key + token, seconds);
    }

    /**
     * 重新更新token超时时间
     *
     * @param token
     * @param seconds 过期时间（秒）
     */
    public void setUserTokenExpire(String token, long seconds) {
        String key = RedisConst.EntityCacheKey.SYSTEM + ":token:";
        LoginUser loginUser = this.getUserByToken(key + token);
        if (null == loginUser || loginUser.getId() == null) {
            return;
        }
        redisUtil.expire(key + "user:" + loginUser.getId(), seconds);
        redisUtil.expire(key + token, seconds);
    }

    /**
     * 重新更新token超时时间
     *
     * @param userId
     * @param seconds 过期时间（秒）
     */
    public void setUserTokenExpire(Integer userId, long seconds) {
        String key = RedisConst.EntityCacheKey.SYSTEM + ":token:";
        String token = this.getTokenByUser(userId);
        if (token == null) {
            return;
        }
        redisUtil.expire(key + "user:" + userId, seconds);
        redisUtil.expire(key + token, seconds);
    }

    /**
     * 根据userId查询token
     *
     * @param userId
     * @return
     */
    public String getTokenByUser(Integer userId) {
        Object object = redisUtil.get(RedisConst.EntityCacheKey.SYSTEM + ":token:user:" + userId);
        if (object != null) {
            return object.toString();
        }
        return null;
    }

    /**
     * 根据token查询userId
     *
     * @param token
     * @return
     */
    public LoginUser getUserByToken(String token) {
        String key = RedisConst.EntityCacheKey.SYSTEM + ":token:";
        Object object = redisUtil.get(key + token);
        if (object != null) {
            LoginUser loginUser = JSON.parseObject(JSON.toJSONString(object), LoginUser.class);
            return loginUser;
        }
        return null;
    }

    /**
     * key: hk:sm:100:1
     *
     * @return 获取传感器最新一条秒级数据
     */
    public Map<Object, Object> getLastSecmeanData(int projectId, int targetSId) {
        //System.out.println("key:"+(RedisConst.EntityCacheKey.SECMEAN + ":" + projectId + ":" + targetSId));
        return redisUtil.hmget(RedisConst.EntityCacheKey.SECMEAN + ":" + projectId + ":" + targetSId);
    }

    /**
     * key: hk:sm:100:1
     *
     * @return 根据指标查询最新一条秒级数据
     */
    public double getLastSecmeanData(int projectId, int targetSId, int quotaCode) {
        //System.out.println("key:"+(RedisConst.EntityCacheKey.SECMEAN + ":" + projectId + ":" + targetSId));

        Object object = redisUtil.hget(RedisConst.EntityCacheKey.SECMEAN + ":" + projectId + ":" + targetSId, "v" + quotaCode);
        if (null != object) {
            return Double.valueOf(object.toString());
        }
        return 0.0d;
    }

    /**
     * key: hk:sm:100:1
     *
     * @return 返回数据最新时间(秒 ）
     */
    public Long getLastSecmeanDataTime(int projectId, int targetSId) {
        //System.out.println("key:"+(RedisConst.EntityCacheKey.SECMEAN + ":" + projectId + ":" + targetSId));
        Object dataTimeObj = redisUtil.hget(RedisConst.EntityCacheKey.SECMEAN + ":" + projectId + ":" + targetSId, "timestamp");
        if (null != dataTimeObj) {
            //dataTime为毫秒
            return Long.parseLong(dataTimeObj.toString());
        }
        return null;
    }

    /**
     * key: hk:sm:warn:100:1
     *
     * @return 返回传感器告警信息
     */
    public String getTargetWarnInfo(int projectId, int targetSId) {
        Object warnObj = redisUtil.get(RedisConst.EntityCacheKey.SECMEAN + ":warn:" + projectId + ":" + targetSId);
        if (null != warnObj) {
            return warnObj.toString();
        }
        return null;
    }

    /**
     * 设置项目状态,key： hk:status:pro:{projectId}
     *
     * @param projectId
     */
    public void setProjectStatus(int projectId, int status) {
        redisUtil.set(RedisConst.EntityCacheKey.STATUS + ":pro:" + projectId, status);
    }

    /**
     * 获取项目状态
     *
     * @param projectId
     * @return
     */
    public int getProjectStatus(int projectId) {
        Object object = redisUtil.get(RedisConst.EntityCacheKey.STATUS + ":pro:" + projectId);
        if (null != object) {
            return (int) object;
        }
        return 0;
    }



    /**
     * 获取项目下所有传感器状态
     * hash
     *
     * @param projectId
     * @return
     */
    public void delProjectTargetsStatus(int projectId) {
        redisUtil.del(RedisConst.EntityCacheKey.STATUS + ":tgs:" + projectId);
    }

    /**
     * 获取项目下所有传感器状态
     * hash
     *
     * @param projectId
     * @return
     */
    public Map<Object, Object> getProjectTargetsStatus(int projectId) {
        return redisUtil.hmget(RedisConst.EntityCacheKey.STATUS + ":tgs:" + projectId);
    }


    /**
     * 传感器状态,key： hk:status:tg:{targetId}
     * @param targetId
     */
//    public void setTargetStatus(int targetId, int status){
//        redisUtil.set(RedisConst.EntityCacheKey.STATUS+":tg:"+targetId, status);
//    }


    /**
     * 获取传感器状态
     *
     * @param targetId
     * @return
     */
    public Integer getTargetStatus(int targetId) {
        Object object = redisUtil.get(RedisConst.EntityCacheKey.STATUS + ":tg:" + targetId);
        if (null != object) {
            return (int) object;
        }
        return 0;
    }


    /**
     * 设置温度变化的步长值
     *
     * @param temperature
     */
    public void setSysJobStep(Double temperature) {
        redisUtil.set(RedisConst.JOB_RUN_STEP, temperature);
    }

    public void setLastSimulationTemperature(Double temperature) {
       redisUtil.set(RedisConst.JOB_RUN_LAST,temperature);
    }

}
